昨天有提一下 rc 檔的使用情境和功能,簡單來說就是做初始化而已,今天我們要自己實作讀取 ~/.goshrc,話不多說馬上開始吧!
首先我們要先確定家目錄 ~ 底下到底有沒有 .goshrc 這個檔案,如果沒有那就不用讀取他了,直接當作沒這回事
如果 ~/.goshrc 存在的話,那就不斷的讀取裡面的指令並且執行,假如裡面有十行 alias xxx='xxx xxxx',那就 逐行執行 直到全部讀完為止
os.UserHomeDir()UserHomeDir() 是用來取得 目前使用者的家目錄(~)路徑,以我自己來說因為我的 username 是 larry,所以我的家目錄就是 /Users/larry
os.Open(filename string) (*File, error)Open 可以用來開啟一個檔案並且得到一個 File 型別的變數,這個 File 變數之後會被用來讀取檔案的內容
bufio.NewReader(rd io.Reader) *bufio.Readerbufio.NewReader 在很久之前的 Day3 有用過,他可以用來把輸入源(包括 File)轉成 bufio.Reader 型別,而 bufio.Reader 型別支援逐行讀取
簡單來說,他跟 os.Open 組合起來就可以逐行讀取檔案
initialize接下來要實作一個 initialize() 來做初始化,也就是逐行執行 ~/.goshrc 的內容
func initialize() {
// 取得家目錄位置,並開啟 ~/.goshrc
homeDir, _ := os.UserHomeDir()
file, err := os.Open(homeDir + "/.goshrc")
// 如果 ~/.goshrc 不存在
// 那就直接結束這個 function
if err != nil {
return
}
// 把 File 轉成 bufio.Reader 型別
// 為後面的逐行讀取做準備
goshrcReader := bufio.NewReader(file)
// 用一個無窮迴圈不斷進行讀取、執行
for {
// 一次從 ~/.goshrc 裡面讀取一行
// input 可能長得像 "alias gst='git status'"
input, err := goshrcReader.ReadString('\n')
// io.EOF 是檔案結尾(End Of File)的意思
// 如果讀取到檔案結束了,代表已經執行完畢
// 就直接結束 function
if err == io.EOF {
return
}
// 把指令頭尾的空白去除掉
input = strings.TrimSpace(input)
// 執行讀取到的指令
// 譬如說執行 "alias gst='git status'"
executeInput(input)
}
}
接著就是到 main() 的開頭執行 initialize(),讓 Shell 一啟動就去讀取 ~/.goshrc
func main() {
initialize() // <--- HERE
/* 以下都是之前在 Day3 寫的 */
/* 不斷顯示 prompt、執行使用者輸入的指令 */
stdin := bufio.NewReader(os.Stdin)
for {
showPrompt()
// ...
executeInput(input)
}
}
為了實驗有沒有成功執行 ~/.goshrc,我在 ~/.goshrc 裡面寫上這些內容,等等看 Shell 在啟動時會不會成功 echo、設定 alias
# ~/.goshrc
echo Hello Larry
alias gst='git status'
alias l='ls -l'
剛進到 Shell 時他就先輸出 Hello Larry,我下 gst 有成功執行 git status、which l 也得到正確的 alias,Gosh 果然沒讓我失望 ???

今天的內容跟很久之前的 Day3 很類似,雖然 Day3 是讀取使用者輸入而今天是讀取檔案,但本質上都是從 Reader(資料來源) 進行讀取,所以做法也很相似
如果對今天的內容有什麼問題歡迎在下方留言,沒問題的話就明天見囉